package com.yugao.fintech.antelope.pay.payment.process;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.yugao.fintech.antelope.pay.common.assembly.PayOrderAssembly;
import com.yugao.fintech.antelope.pay.common.constants.PayCacheKey;
import com.yugao.fintech.antelope.pay.common.constants.PayNodeEnum;
import com.yugao.fintech.antelope.pay.common.service.PayNodeService;
import com.yugao.fintech.antelope.pay.common.service.PayOrderService;
import com.yugao.fintech.antelope.pay.model.entity.PayNode;
import com.yugao.fintech.antelope.pay.model.entity.PayOrder;
import com.yugao.fintech.antelope.pay.payment.channel.AbstractPayOrderCloseService;
import com.yugao.fintech.antelope.pay.payment.channel.AbstractPayOrderQueryService;
import com.yugao.fintech.antelope.pay.payment.channel.IPayOrderCloseService;
import com.yugao.fintech.antelope.pay.payment.channel.IPayOrderQueryService;
import com.yugao.fintech.antelope.pay.payment.model.bo.MchAppConfigContext;
import com.yugao.fintech.antelope.pay.payment.model.rqrs.ChannelRetMsgExt;
import com.yugao.fintech.antelope.pay.payment.service.ConfigContextQueryService;
import com.yugao.fintech.antelope.pay.payment.service.PayMchNotifyService;
import com.yugao.fintech.framework.core.response.Resp;
import com.yugao.fintech.framework.core.response.RetOps;
import com.yugao.fintech.framework.lock.manager.ILockManager;
import com.yugao.fintech.framework.lock.model.ILock;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 查询上游订单， &  补单服务实现类
 *

 */
@Slf4j
@Service
public class ChannelPayOrderProcess {
    @Autowired
    private ConfigContextQueryService configContextQueryService;
    @Autowired
    private PayOrderService payOrderService;
    @Autowired
    private PayNodeService payNodeService;
    @Autowired
    private PayMchNotifyService payMchNotifyService;
    @Autowired
    private ILockManager lockManager;
    @Autowired
    private PayOrderAssembly payOrderAssembly;

    /**
     * 关闭订单
     * @param isTimeoutClose 是福哦为超时关闭
     */
    @Transactional(rollbackFor = Exception.class)
    public Resp<ChannelRetMsgExt> processClosePayOrder(String payOrderNo, boolean isTimeoutClose) {
        PayNodeEnum closeOk = isTimeoutClose ? PayNodeEnum.CLOSE_OK_TIMEOUT : PayNodeEnum.CLOSE_OK;
        PayNodeEnum closeFail = isTimeoutClose ? PayNodeEnum.CLOSE_FAIL_TIMEOUT : PayNodeEnum.CLOSE_FAIL;

        PayNode payNode = PayNode.builder().titleCode(closeOk.getCode()).build();
        ILock lock = lockManager.getLock(PayCacheKey.PAY_GLOBAL_LOCK.formatKey(payOrderNo));
        boolean tryLock = lock.tryLock(5, TimeUnit.SECONDS);
        if (!tryLock) {
            return Resp.fail("操作过于频繁");
        }
        try {
            // 校验订单是否存在
            PayOrder payOrder = payOrderService.getByPayOrderNo(payOrderNo);
            if (Objects.isNull(payOrder)) {
                log.warn("支付订单 payOrderNo={} 不存在", payOrderNo);
                return Resp.fail("订单不存在");
            }

            // 判断是否已经关闭
            if (PayOrder.STATE_CLOSED.equals(payOrder.getStatus())) {
                log.info("当前订单已关闭, payOrderNo: {}, status: {}", payOrderNo, payOrder.getStatus());
                return Resp.ok();
            }

            // 如果不是待支付和支付中状态, 不允许操作
            if (!PayOrder.STATE_INIT.equals(payOrder.getStatus()) && !PayOrder.STATE_ING.equals(payOrder.getStatus())) {
                log.info("当前订单不可关闭, payOrderNo: {}, status: {}", payOrderNo, payOrder.getStatus());
                return Resp.fail("当前订单不可关闭");
            }

            // 如果是待支付状态, 说明没有和第三方支付平台交互-微信/支付宝/银联等(直接取消)
            if (StrUtil.equals(PayOrder.STATE_INIT, payOrder.getStatus())) {
                payOrderService.updateInit2Close(payOrder.getPayOrderNo());
                payOrder.setStatus(PayOrder.STATE_CLOSED);
                processPayNode(payNode, payOrder);
                return Resp.ok(null, "关单成功");
            }

            /*
             * 步骤
             * 1. 如果订单未创建, 则更新平台端的订单状态
             * 2. 如果订单已支付, 则更新平台订单状态
             * 3, 如果订单未支付, 则调用关单接口关闭订单, 并更新商户端订单状态
             */

            /* 支付中, 需要向第三方支付平台查询状态 */
            payNode.setPayOrderNo(payOrderNo);

            // 查询支付接口是否存在
            IPayOrderQueryService queryService = AbstractPayOrderQueryService.getService(payOrder.getIfCode());

            // 支付通道接口实现不存在
            if (queryService == null) {
                payNode.setPayOrderNo(null);
                log.error("{} interface not exists!", payOrder.getIfCode());
                return Resp.fail("未实现接口代码对应的查询服务");
            }

            // 查询出商户应用的配置信息
            MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfo(payOrder.getMchNo(), payOrder.getAppId());

            ChannelRetMsgExt channelRetMsgExt = queryService.query(payOrder, mchAppConfigContext);
            if (channelRetMsgExt == null) {
                log.error("channelRetMsg is null");
                return Resp.fail("通道返回接口为空");
            }

            log.info("补单[{}]查询结果为：{}", payOrderNo, JSON.toJSONString(channelRetMsgExt));

            // 查询成功
            if (channelRetMsgExt.getChannelState() == ChannelRetMsgExt.ChannelState.CONFIRM_SUCCESS) {
                if (payOrderService.updateIng2Success(payOrderNo, channelRetMsgExt)) {
                    // 订单支付成功，其他业务逻辑
                    payNode.setTitleCode(PayNodeEnum.PAY_OK.getCode());
                    this.confirmSuccess(payOrder);
                }
            } else if (channelRetMsgExt.getChannelState() == ChannelRetMsgExt.ChannelState.CONFIRM_FAIL) {  //确认失败
                payNode.setTitleCode(closeFail.getCode());
                // 更新支付订单表为失败状态
                payOrderService.updateIng2Fail(payOrderNo, channelRetMsgExt);
            } else if (channelRetMsgExt.getChannelState() == ChannelRetMsgExt.ChannelState.WAITING) {
                Resp<ChannelRetMsgExt> channelRetMsgResp = closeChannelOrder(payOrder, mchAppConfigContext);
                if (!RetOps.of(channelRetMsgResp).isSuccess()) {
                    payNode.setTitleCode(closeFail.getCode());
                }
                return channelRetMsgResp;
            }
            return Resp.ok(channelRetMsgExt);
        } catch (Exception e) {  //继续下一次迭代查询
            payNode.setTitleCode(closeFail.getCode());
            log.error("error payOrderNo = {}", payOrderNo, e);
        } finally {
            lock.unlock();
            payNodeService.savePayNode(payNode);
        }
        return Resp.fail("系统异常");
    }

    private void processPayNode(PayNode payNode, PayOrder payOrder) {
        if (PayOrder.STATE_CLOSED.equals(payOrder.getStatus())) {
            payNode.setTitleCode(PayNodeEnum.CLOSE_OK.getCode());
        } else if (PayOrder.STATE_SUCCESS.equals(payOrder.getStatus())) {
            payNode.setTitleCode(PayNodeEnum.PAY_OK.getCode());
        }
        if (StringUtils.isNotEmpty(payNode.getTitleCode())) {
            payNode.setPayOrderNo(payOrder.getPayOrderNo());
        }
    }

    /**
     * 调用渠道关闭订单
     */
    private Resp<ChannelRetMsgExt> closeChannelOrder(PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
        String payOrderNo = payOrder.getPayOrderNo();
        // 查询支付接口是否存在
        IPayOrderCloseService closeService = AbstractPayOrderCloseService.getService(payOrder.getIfCode());

        // 支付通道接口实现不存在
        if (Objects.isNull(closeService)) {
            log.error("{} interface not exists!", payOrder.getIfCode());
            return Resp.fail(payOrder.getIfCode() + " interface not exists!");
        }

        ChannelRetMsgExt channelRetMsgExt = closeService.close(payOrder, mchAppConfigContext);
        if (channelRetMsgExt == null) {
            log.error("channelRetMsg is null");
            return Resp.fail("通道响应结果为空");
        }

        log.info("关闭订单[{}]结果为：{}", payOrderNo, JSON.toJSONString(channelRetMsgExt));

        // 关闭订单成功
        if (channelRetMsgExt.getChannelState() == ChannelRetMsgExt.ChannelState.CONFIRM_SUCCESS) {
            payOrderService.updateIng2Close(payOrderNo);
        } else {
            return Resp.fail(channelRetMsgExt.getChannelErrMsg());
        }
        return Resp.ok(channelRetMsgExt);
    }


    /**
     * 明确成功的处理逻辑（除更新订单其他业务）
     */
    public void confirmSuccess(PayOrder payOrder) {
        // 设置订单状态
        payOrder.setStatus(PayOrder.STATE_SUCCESS);

        // 自动分账 处理逻辑， 不影响主订单任务
//        this.updatePayOrderAutoDivision(payOrder);
//
        // 发送商户通知
        payMchNotifyService.payOrderNotify(payOrder);
    }

    /**
     * 更新订单自动分账业务
     */
    private void updatePayOrderAutoDivision(PayOrder payOrder) {

//        try {
//
//            //默认不分账  || 其他非【自动分账】逻辑时， 不处理
//            if(payOrder == null || payOrder.getDivisionMode() == null || payOrder.getDivisionMode() != PayOrder.DIVISION_MODE_AUTO){
//                return ;
//            }
//
//            //更新订单表分账状态为： 等待分账任务处理
//            boolean updDivisionState = payOrderService.update(new LambdaUpdateWrapper<PayOrder>()
//                    .set(PayOrder::getDivisionState, PayOrder.DIVISION_STATE_WAIT_TASK)
//                    .eq(PayOrder::getPayOrderId, payOrder.getPayOrderId())
//                    .eq(PayOrder::getDivisionState, PayOrder.DIVISION_STATE_UNHAPPEN)
//            );
//
//            if(updDivisionState){
//                //推送到分账MQ
//                mqSender.send(PayOrderDivisionMQ.build(payOrder.getPayOrderId(), CS.YES,null), 80); //80s 后执行
//            }
//
//        } catch (Exception e) {
//            log.error("订单[{}]自动分账逻辑异常：", payOrder.getPayOrderId(), e);
//        }
    }
}
